/*
 * Clase que instancia la matriz que representa el terreno.
 */
package fuente;

import fuente.estructuras.DLL;
import fuente.estructuras.DLLNode;

public class Matriz {
    private Matriz.Node _primeraColumna;
    private int _lengthColumna;
    
    /**
     * Constructor, crea una nueva matriz de terreno e 
     * inicializa el numero de columnas y el primer nodo
     */
    public Matriz () {
        _primeraColumna = null;
        _lengthColumna = 0;
    }
    
    /**
     * Inserta una columna de celdas a la matriz.
     * @param pColumna Columna de celdas a insertar
     */
    public void insertar (DLL pColumna) {
        Matriz.Node ins = new Matriz.Node(pColumna);
        
        if (getPrimeraColumna() == null) {
            _primeraColumna = ins;
        }
        else {
            Matriz.Node tmp = getPrimeraColumna();
            while (tmp._siguiente != null) {
                tmp = tmp._siguiente;
            }
            tmp._siguiente = ins;
            ins._anterior = tmp;
        }
        _lengthColumna ++;
    }

    /* Inicio implementaciones de getters y setters */
    /**
     * Obtiene la referencia al primer nodo de columnas.
     * @return La primera columna
     */
    public Matriz.Node getPrimeraColumna () {
        return _primeraColumna;
    }
    
    /**
     * Obtiene la cantidad de filas de la matriz.
     * @return Cantidad de filas
     */
    public int getLengthFilas () {
        return getPrimeraColumna()._lengthFilas;
    }

    /**
     * Obtiene la cantidad de columnas de la matriz.
     * @return Cantidad de Columnas
     */
    public int getLengthColumna () {
        return _lengthColumna;
    }
    
    /**
     * Busca un elemento dentro de la matriz de acuerdo
     * a su ubicacion por indices en columnas y filas.
     * @param pIndI Indice de Columnas
     * @param pIndJ Indice de Filas
     * @return El dato de la celda
     */
    public String getDato (int pIndI, int pIndJ) {
        int countC = 1;
        for (Matriz.Node nC = _primeraColumna; nC != null; nC = nC._siguiente) {
            if (countC == pIndI) {
                int countF = 1;
                for (DLLNode nF = nC._celdas.getHead(); nF != null; nF = nF.getSucc()) {
                    if (countF == pIndJ) {
                        return (String)nF.getData();
                    }
                    else {
                        countF ++;
                    }
                }
                System.out.println("Indice de Fila fuera de los limites");
                return null;
            }
            else {
                countC ++;
            }
        }
        System.out.println("Indice de Columnas fuera de los limites");
        return null;
    }
    /* Final implementaciones de getters y setters */
    
    
    /*
     * Clase interna que permite crear un nuevo nodo que representa una columna.
     */
    public static class Node {
        private DLL _celdas;
        private int _lengthFilas;
        private Node _siguiente;
        private Node _anterior;
        
        /**
         * Constructor, crea un nuevo nodo para contener 
         * las celdas de una columna.
         * @param pDato Lista de celdas
         */
        public Node (DLL pDato) {
            _celdas = pDato;
            _lengthFilas = pDato.getLength();
            _siguiente = _anterior = null;
        }
    }
}
